package com.team.frame.controller.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static com.alipay.api.AlipayConstants.*;


/**
 * Created by lidan on 2017/2/7.
 */
@Controller
@RequestMapping(value = "/alipay/app/pay")
public class AliPayController {

    //沙箱支付宝网关
    private static final String SERVER_URL_DEV = "https://openapi.alipaydev.com/gateway.do";
    //支付宝网关
    private static final String SERVER_URL = "https://openapi.alipay.com/gateway.do";
    //APP_ID
    private static final String APP_ID = "2016072800110927";
    //支付宝应用私钥 APP_PRIVATE_KEY
    private static final String APP_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDFR8lZHWkFreLjionAAxzKizan0L8hlM8gnFx+iN1ypOaODQHDfuuCV7Y8JqKc3WvrnOyR/061gUZ+fdmzYCst4hZ4+i19U+VeQowgCUTovGQpf7domxIW5Kh1jdpPq/anUbzcIjY6PBDFOVKf7J/Frt7J0rB/bWhvTUo4E52CePJeLSSjxuYHiDWL4qZUh9+47HKJ1MwxtciApaO2NR9jxWbHkmVFGkM1F/yg7F+PCzrJhNReW8vLcN1wQzBPH3KClG7M5GUIS5E9IXuwMFow0rXw52tjT7fcOUmvZqIFfUNtXfidvXuoXJRhDDVs5s9Z1Zup+KBYu4qVO3S7iinRAgMBAAECggEAIGPQ4xi5DX2nKsSsKSJZr8d7icH0H4dXGnuRlBTUhuYcFGZ+S6Ki+Bt+iBGv0SFpfp2dGbtZKOO4tzvialj3vejI18P7hAAqQHecmgXrkmqb51RYwIv1RFz2a5aGqV4KeR4qa9oSHS2Pc1IeBrPK56H2Yhx9be6AnwWJkftmeO0oqqCeP3A26xted20WCI1cF8U7yQflISLRVPs0dhwkua4MI9bFCFiQRVT9A1OU0knbD2bbp43VArvM3Gdh5SmWGUX9oDjQWuAxT+vz7WpMfHOgvyLpM2uhyy2ZeAlTrRS9T/gEpGKV3KC5AfA+aVhgHfpk8h6+5xEVXgTyLZhCAQKBgQDvzkTfkqUYwSyB0Qnd0IJxIJWQz3Dyti/4TThc3qQKjy+4w4OxRtqGVbzYcvXLDf2OPK7wYJXcg9xLz/OGNO9g/Eikai+u6zG/auphGHRaVHAauRDuS4VlThp8A7cFS44+icT4Nx+vgQ8wMMVs6dUeXS6VOqpP3clczxMHIeyR6QKBgQDSmlhbJPaij5UlSwkwTeKuPC+WllRJLzMmPKUzZYq7nYMULj4TXy+8KUVjLDxt6rh3m3IVIqmoFL3hj9dp2fZRyiXwr3KmzJOIut6BuLRXQRHH4Yd95NsjYWf4vhT44tiAr1G07HCifS1H9KwIbTWhOnOQs1udC/s1mV/Pj9m/qQKBgAnUDGKVYgrXr/lKFftvVklIqpiax+hKq0Cj+ZFk1phQMgaCjN0xKDelP+4nGAfQdPnlZs4XR00YYmkBBtwTQ1RYQqnqaDXlEc7klOKR3ALvvwB5YUZC9h6mytMWW+PtqtDJWLdLmxLYWUUCWrUSCFgMPaKEGwLW9i/FlOQP8eAxAoGAO0Nnna5XIQOairYEzez83t7c3VlMOpPnptjl/AKU+ZqnaiRhH35npmFOv0uRbbThV/cMMVpht4SusiySB51oLTffWU1ly/5BffZn6sUZKnyLDl4ujIS8Dca5RUvoBul+1yd+rJTkVTU4ask1J+Hjd41FO/Dc1OKsPDb+uR/XvJECgYEAyWwy8Z9fCKnPZamsUrfEAKVCV318dnMYGH8tEzXHfw2LaqkxcYyxJLhgrHGk/C1yUpJ6XJs0zADAJ+V3B3hKl0Ea7LivQmgzSwOCXVmWSoVXD7uAvt1xKwQ1J7b5W9r9kSspWGeTVNDFa3e1iyzJzoIMAOpbU2LoEW9ZRYMg2Xo=";
    //支付宝应用公钥 APP_PUBLIC_KEY（此参数暂时没有用到）
    private static final String APP_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxUfJWR1pBa3i44qJwAMcyos2p9C/IZTPIJxcfojdcqTmjg0Bw37rgle2PCainN1r65zskf9OtYFGfn3Zs2ArLeIWePotfVPlXkKMIAlE6LxkKX+3aJsSFuSodY3aT6v2p1G83CI2OjwQxTlSn+yfxa7eydKwf21ob01KOBOdgnjyXi0ko8bmB4g1i+KmVIffuOxyidTMMbXIgKWjtjUfY8Vmx5JlRRpDNRf8oOxfjws6yYTUXlvLy3DdcEMwTx9ygpRuzORlCEuRPSF7sDBaMNK18OdrY0+33DlJr2aiBX1DbV34nb17qFyUYQw1bObPWdWbqfigWLuKlTt0u4op0QIDAQAB";
    //支付宝公钥 ALIPAY_PUBLIC_KEY
    private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu/RJugjnvLPUUjLgr3FHGSHoB9OjDQ7WLy6hSSu3ZgEXCUDwFr5h56MGhb8EMjke7P4oBY6Q2xC2fwASnCeAqSj1MRmceibpkLOFF7D1cdBSjej0BzsrCC9cpBPykuoAJvudwGSi5z3Dl8nF29g80bhj4Qrwfk54uKY5iZkiO+AhCXhvj2BIqCKih9/VW+2yD2rt41l3GpB/xPQ8yqkukm+82O9zS99gunm5ON77OFN4za3s0axC1+ceGpMHFfzdmdGcFwjjr0E+JGm6adklWGhOyIf4j/jZcdviTpP8Gwfy0p8qkfTs9a44IurIFw3Y5K8RgAZTvX3keJlVzgbQTwIDAQAB";


    /**
     * 支付宝APP支付调用接口
     *
     * @param body        对一笔交易的具体描述信息(不是必传)
     * @param subject     商品的标题/交易标题/订单标题/订单关键字等
     * @param totalAmount 订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
     * @param outTradeNo  商户网站唯一订单号
     * @param notifyUrl   支付宝服务器主动通知商户服务器里指定的页面http/https路径。通知商户服务器里指定的页面http/https路径。 https://api.xx.com/receive_notify.htm
     */
    @RequestMapping(value = "/data")
    @ResponseBody
    public void getAppPayData(String body, String subject, String outTradeNo, String totalAmount, String notifyUrl) {
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(SERVER_URL, APP_ID, APP_PRIVATE_KEY, FORMAT_JSON, CHARSET_UTF8, ALIPAY_PUBLIC_KEY, SIGN_TYPE_RSA2);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        if (!org.apache.commons.lang3.StringUtils.isBlank(body)) {
            model.setBody(body);
        }
        model.setSubject(subject);
        model.setOutTradeNo(outTradeNo);
        model.setTimeoutExpress("30m");
        model.setTotalAmount(totalAmount);
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
//        request.setNotifyUrl("http://gotoshare.online:83/alipay/app/pay/callback.json");
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            System.out.println(response.getBody());//就是orderString 可以直接给客户端请求，无需再做处理。
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    }

    /**
     * 支付宝回调服务器接口地址
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/callback")
    @ResponseBody
    public void payCallBack(HttpServletRequest request, HttpServletResponse response) {
        try {
            //获取支付宝POST过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                //乱码解决，这段代码在出现乱码时使用。
                //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
            // TODO: 2017/2/27 商户订单号，交易流水号
            //商户订单号
            String outTradeNo = request.getParameter("out_trade_no");
            //支付宝交易号（流水号）
            String tradeNo = request.getParameter("trade_no");
            String tradeStatus = request.getParameter("trade_status");

            //切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            //boolean flag = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET_UTF8, "RSA2");
            if (AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET_UTF8, SIGN_TYPE_RSA2)) {
                System.out.println("支付宝验签成功！！！======trade_status：" + tradeStatus);
                if (tradeStatus.equals("TRADE_FINISHED") || tradeStatus.equals("TRADE_SUCCESS")) {
                    //TODO 支付宝支付成功（处理）
                }
                response.getWriter().write("success");
            } else {//验证失败
                System.out.println("支付宝验签失败！！！");
                response.getWriter().write("failure");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**    此方法会去掉sign_type做验签，暂时除生活号（原服务窗）激活开发者模式外都使用V1。
     @param params 参数列表(包括待验签参数和签名值sign) key-参数名称 value-参数值
     @param publicKey 验签公钥
     @param charset 验签字符集
     **/
    //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)

    /**
     * 此方法不会去掉sign_type验签，用于生活号（原服务窗）激活开发者模式
     *
     * @param params    参数列表(包括待验签参数和签名值sign) key-参数名称 value-参数值
     * @param publicKey 验签公钥
     * @param charset   验签字符集
     **/
    //boolean AlipaySignature.rsaCheckV2(Map<String, String> params, String publicKey, String charset, String sign_type)



    /**
     * 支付宝交易退款接口
     * @param out_trade_no 订单支付时传入的商户订单号,不能和 trade_no同时为空。 “20150320010101001”
     * @param trade_no 支付宝交易号，和商户订单号不能同时为空 	“2014112611001004680073956707”
     * @param refund_amount 需要退款的金额，该金额不能大于订单金额,单位为元，支持两位小数 	“200.12”
     * @param refund_reason 退款的原因说明 	“正常退款”
     * @param out_request_no 标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。 	“HZ01RF001”
     * @param operator_id 商户的操作员编号(不是必传) 	 “OP001”
     * @param store_id 商户的门店编号(不是必传) 	“NJ_S_001”
     * @param terminal_id 商户的终端编号(不是必传) 	“NJ_T_001”
     */
    @RequestMapping(value = "/traderefund")
    @ResponseBody
    public void tradeRefund(String out_trade_no,String trade_no,String refund_amount,String refund_reason,String out_request_no,String operator_id,String store_id,String terminal_id) {
        AlipayClient alipayClient = new DefaultAlipayClient(SERVER_URL, APP_ID, APP_PRIVATE_KEY, FORMAT_JSON, CHARSET_UTF8, ALIPAY_PUBLIC_KEY, SIGN_TYPE_RSA2);
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(out_trade_no);
        model.setTradeNo(trade_no);
        model.setRefundAmount(refund_amount);
        model.setRefundReason(refund_reason);
        model.setOutRequestNo(out_request_no);
        if (!org.apache.commons.lang3.StringUtils.isBlank(operator_id)) {
            model.setOperatorId(operator_id);
        }
        if (!org.apache.commons.lang3.StringUtils.isBlank(store_id)) {
            model.setStoreId(store_id);
        }
        if (!org.apache.commons.lang3.StringUtils.isBlank(terminal_id)) {
            model.setTerminalId(terminal_id);
        }
        request.setBizModel(model);
        try {
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                System.out.println("调用成功");
                // TODO: 2017/2/28 退款调用成功
            } else {
                System.out.println("调用失败");
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

    }


}